import os
import tkinter as tk
from tkinter import filedialog, ttk, messagebox, simpledialog
import shutil
import threading
from pathlib import Path

class FileCopyTool:
    def __init__(self, root):
        self.root = root
        self.root.title("文件/文件夹复制工具")
        self.root.geometry("600x400")
        self.root.resizable(True, True)
        
        # 设置中文字体
        self.style = ttk.Style()
        self.style.configure("TLabel", font=("SimHei", 10))
        self.style.configure("TButton", font=("SimHei", 10))
        self.style.configure("TCombobox", font=("SimHei", 10))
        
        # 创建界面框架
        self.create_widgets()
        
        # 存储选择的文件/文件夹和目标文件夹
        self.source_items = []
        self.destination_folders = []
        
    def create_widgets(self):
        # 源文件/文件夹选择区域
        source_frame = ttk.LabelFrame(self.root, text="选择要复制的文件/文件夹")
        source_frame.pack(fill="x", padx=10, pady=5)
        
        ttk.Button(source_frame, text="选择文件", command=self.select_files).pack(side="left", padx=5, pady=5)
        ttk.Button(source_frame, text="选择文件夹", command=self.select_folders).pack(side="left", padx=5, pady=5)
        ttk.Button(source_frame, text="清除选择", command=self.clear_source).pack(side="left", padx=5, pady=5)
        
        # 源文件列表显示
        self.source_listbox = tk.Listbox(self.root, height=5, font=("SimHei", 10))
        self.source_listbox.pack(fill="x", padx=10, pady=5)
        scrollbar = ttk.Scrollbar(self.source_listbox, command=self.source_listbox.yview)
        scrollbar.pack(side="right", fill="y")
        self.source_listbox.config(yscrollcommand=scrollbar.set)
        
        # 目标文件夹选择区域
        dest_frame = ttk.LabelFrame(self.root, text="选择目标文件夹")
        dest_frame.pack(fill="x", padx=10, pady=5)
        
        ttk.Button(dest_frame, text="选择目标文件夹", command=self.select_destinations).pack(side="left", padx=5, pady=5)
        ttk.Button(dest_frame, text="清除目标", command=self.clear_destinations).pack(side="left", padx=5, pady=5)
        
        # 目标文件夹列表显示
        self.dest_listbox = tk.Listbox(self.root, height=5, font=("SimHei", 10))
        self.dest_listbox.pack(fill="x", padx=10, pady=5)
        scrollbar_dest = ttk.Scrollbar(self.dest_listbox, command=self.dest_listbox.yview)
        scrollbar_dest.pack(side="right", fill="y")
        self.dest_listbox.config(yscrollcommand=scrollbar_dest.set)
        
        # 复制按钮
        ttk.Button(self.root, text="开始复制", command=self.start_copying).pack(pady=10)
        
        # 进度和状态显示
        self.progress = ttk.Progressbar(self.root, orient="horizontal", length=100, mode="determinate")
        self.progress.pack(fill="x", padx=10, pady=5)
        
        self.status_var = tk.StringVar()
        self.status_var.set("准备就绪")
        ttk.Label(self.root, textvariable=self.status_var, font=("SimHei", 10)).pack(fill="x", padx=10, pady=5)
    
    def select_files(self):
        files = filedialog.askopenfilenames(title="选择文件")
        if files:
            self.source_items.extend(files)
            self.update_source_list()
    
    def select_folders(self):
        # 创建自定义对话框让用户输入多个文件夹路径
        folder_paths = self._ask_multiple_folders("选择要复制的文件夹")
        if folder_paths:
            self.source_items.extend(folder_paths)
            self.update_source_list()
    
    def select_destinations(self):
        # 创建自定义对话框让用户输入多个目标文件夹路径
        folder_paths = self._ask_multiple_folders("选择目标文件夹")
        if folder_paths:
            self.destination_folders.extend(folder_paths)
            self.update_dest_list()
    
    def _ask_multiple_folders(self, title):
        """创建自定义对话框让用户输入多个文件夹路径"""
        dialog = MultipleFolderDialog(self.root, title)
        return dialog.result
    
    def update_source_list(self):
        self.source_listbox.delete(0, tk.END)
        for item in self.source_items:
            self.source_listbox.insert(tk.END, os.path.basename(item) if os.path.isfile(item) else item)
    
    def update_dest_list(self):
        self.dest_listbox.delete(0, tk.END)
        for folder in self.destination_folders:
            self.dest_listbox.insert(tk.END, os.path.basename(folder))
    
    def clear_source(self):
        self.source_items = []
        self.update_source_list()
    
    def clear_destinations(self):
        self.destination_folders = []
        self.update_dest_list()
    
    def start_copying(self):
        if not self.source_items or not self.destination_folders:
            messagebox.showwarning("警告", "请先选择要复制的项目和目标文件夹")
            return
        
        # 禁用复制按钮，防止重复点击
        self.status_var.set("正在准备复制...")
        self.progress["value"] = 0
        
        # 在新线程中执行复制操作，避免界面卡顿
        copy_thread = threading.Thread(target=self.perform_copying)
        copy_thread.daemon = True
        copy_thread.start()
    
    def perform_copying(self):
        try:
            total_tasks = len(self.source_items) * len(self.destination_folders)
            completed_tasks = 0
            
            for source in self.source_items:
                source_name = os.path.basename(source)
                for dest_folder in self.destination_folders:
                    # 确保目标文件夹存在
                    if not os.path.exists(dest_folder):
                        os.makedirs(dest_folder)
                    
                    # 构建目标路径
                    if os.path.isfile(source):
                        dest_path = os.path.join(dest_folder, source_name)
                        # 复制文件
                        shutil.copy2(source, dest_path)
                    else:
                        dest_path = os.path.join(dest_folder, source_name)
                        # 复制文件夹
                        if os.path.exists(dest_path):
                            shutil.rmtree(dest_path)
                        shutil.copytree(source, dest_path)
                    
                    # 更新进度
                    completed_tasks += 1
                    progress = (completed_tasks / total_tasks) * 100
                    
                    # 使用普通函数替代lambda表达式进行赋值
                    def update_progress(p=progress):
                        self.progress["value"] = p
                    
                    def update_status(msg=f"正在复制: {source_name} 到 {os.path.basename(dest_folder)}"):
                        self.status_var.set(msg)
                    
                    self.root.after(0, update_progress)
                    self.root.after(0, update_status)
            
            # 复制完成
            self.root.after(0, lambda: self.progress.stop())
            self.root.after(0, lambda: self.status_var.set("复制完成!"))
            messagebox.showinfo("成功", "所有项目已复制完成!")
            
        except Exception as e:
            self.root.after(0, lambda: self.progress.stop())
            self.root.after(0, lambda: self.status_var.set(f"复制出错: {str(e)}"))
            messagebox.showerror("错误", f"复制过程中发生错误:\n{str(e)}")

class MultipleFolderDialog(simpledialog.Dialog):
    def __init__(self, parent, title=None):
        self.result = None
        super().__init__(parent, title)
    
    def body(self, master):
        ttk.Label(master, text="请输入文件夹路径，多个路径用分号(;)分隔:").pack(anchor=tk.W, padx=5, pady=5)
        
        self.path_entry = ttk.Entry(master, width=50)
        self.path_entry.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Button(master, text="浏览...", command=self.browse_folder).pack(anchor=tk.E, padx=5, pady=5)
        
        return self.path_entry  # 初始焦点
    
    def browse_folder(self):
        folder = filedialog.askdirectory(title="选择文件夹")
        if folder:
            current_text = self.path_entry.get()
            if current_text:
                self.path_entry.insert(tk.END, f";{folder}")
            else:
                self.path_entry.insert(tk.END, folder)
    
    def apply(self):
        paths_text = self.path_entry.get()
        if paths_text:
            # 分割路径并去除空白
            paths = [path.strip() for path in paths_text.split(';') if path.strip()]
            # 验证路径是否存在
            valid_paths = []
            for path in paths:
                if os.path.exists(path) and os.path.isdir(path):
                    valid_paths.append(path)
                else:
                    messagebox.showerror("错误", f"路径不存在或不是文件夹: {path}")
            
            if valid_paths:
                self.result = valid_paths

if __name__ == "__main__":
    root = tk.Tk()
    app = FileCopyTool(root)
    root.mainloop()